<script setup lang="tsx">
import type { TreeOverrideNodeClickBehavior } from 'naive-ui';
import { NButton, NDropdown, NFormItem, NInput, NSwitch, NTag } from 'naive-ui';
import { h, onMounted, ref, shallowRef } from 'vue';
import { useBoolean } from '@sa/hooks';
import type { User } from '@/service/api';
import {
  deleteUsers,
  fetchAllDeptOptions,
  fetchGetUserList,
  getFetchUserUrl,
  updateUserPassword,
  updateUserStatus
} from '@/service/api';
import { $t } from '@/locales';
import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table';
import { CommonStatusEnum } from '@/constants/common';
import { useAuth } from '@/hooks/business/auth';
import SvgIcon from '@/components/custom/svg-icon.vue';
import { DICT_TYPE, getDictObj } from '@/utils/dict';
import UserSearch from './modules/user-search.vue';
import UserOperateModal from './modules/user-operate-model.vue';
import UserAssignRoleModal from './modules/user-assign-role-model.vue';

const appStore = useAppStore();
const { hasAuth } = useAuth();

const { bool: userAssignRoleVisible, setTrue: openUserAssignRoleModal } = useBoolean();

const {
  columns,
  columnChecks,
  data,
  getData,
  getDataByPage,
  loading,
  mobilePagination,
  searchParams,
  resetSearchParams
} = useTable({
  apiFn: fetchGetUserList,
  showTotal: true,
  apiParams: {
    current: 1,
    size: 10,
    // if you want to use the searchParams in Form, you need to define the following properties, and the value is null
    // the value can not be undefined, otherwise the property in Form will not be reactive
    status: null,
    username: null,
    gender: null,
    nickname: null,
    mobile: null,
    email: null,
    deptId: null
  },
  columns: () => [
    {
      type: 'selection',
      align: 'center',
      width: 48
    },
    {
      key: 'id',
      title: $t('common.index'),
      align: 'center',
      width: 64
    },
    {
      key: 'username',
      title: $t('page.manage.user.userName'),
      align: 'center',
      minWidth: 50
    },
    {
      key: 'gender',
      title: $t('page.manage.user.userGender'),
      align: 'center',
      width: 100,
      render: row => {
        if (row.gender === null) {
          return null;
        }
        const dictObj = getDictObj(DICT_TYPE.SYSTEM_USER_SEX, row.gender);

        return <NTag type={dictObj?.colorType}>{dictObj?.label}</NTag>;
      }
    },
    {
      key: 'nickname',
      title: $t('page.manage.user.nickName'),
      align: 'center',
      minWidth: 50
    },
    {
      key: 'deptName',
      title: $t('page.manage.user.deptName'),
      align: 'center',
      minWidth: 120
    },
    {
      key: 'mobile',
      title: $t('page.manage.user.userPhone'),
      align: 'center',
      width: 120
    },
    {
      key: 'email',
      title: $t('page.manage.user.userEmail'),
      align: 'center',
      minWidth: 200
    },
    {
      key: 'remark',
      title: $t('page.manage.user.userRemark'),
      align: 'center',
      minWidth: 100
    },
    {
      key: 'status',
      title: $t('page.manage.user.userStatus'),
      align: 'center',
      width: 100,
      render: row => {
        if (row.status === null) {
          return null;
        }
        // eslint-disable-next-line prefer-const
        let status = row.status.toString();
        return (
          <div>
            <NSwitch
              checkedValue="1"
              uncheckedValue="0"
              v-model:value={status}
              onUpdate:value={() => handleUserStatus(row)}
            ></NSwitch>
          </div>
        );
      }
    },
    {
      key: 'operate',
      title: $t('common.operate'),
      align: 'center',
      width: 200,
      render: row => (
        <div class="flex-center gap-8px">
          <div v-show={hasAuth('system:user:update')}>
            <NButton type="primary" ghost size="small" onClick={() => edit(row.id)}>
              {{
                default: () => $t('common.edit'),
                icon: () => h(SvgIcon, { icon: 'ep:edit' })
              }}
            </NButton>
          </div>
          <div v-show={hasAuth(['system:user:update-password', 'system:user:delete'])}>
            <NDropdown
              trigger="hover"
              options={[
                {
                  label: $t('common.delete'),
                  show: hasAuth('system:user:delete'),
                  key: 'delete',
                  icon: () => h(SvgIcon, { icon: 'ep:delete' }),
                  props: {
                    onClick: () => {
                      handleDelete(row.id);
                    }
                  }
                },
                {
                  label: $t('page.manage.user.resetPassword'),
                  show: hasAuth('system:user:update-password'),
                  key: 'resetPwd',
                  icon: () => h(SvgIcon, { icon: 'ep:key' }),
                  props: {
                    onClick: () => {
                      handleResetPwd(row);
                    }
                  }
                },
                {
                  label: $t('page.manage.user.assignUserRole'),
                  show: hasAuth('system:permission:assign-user-role'),
                  key: 'assignUserRole',
                  icon: () => h(SvgIcon, { icon: 'ep:circle-check' }),
                  props: {
                    onClick: () => {
                      handleUserAssignRole(row);
                    }
                  }
                }
              ]}
            >
              {{
                default: () => (
                  <NButton type="error" size="small" ghost>
                    {{
                      default: () => $t('common.more'),
                      icon: () => h(SvgIcon, { icon: 'ep:d-arrow-right' })
                    }}
                  </NButton>
                )
              }}
            </NDropdown>
          </div>
        </div>
      )
    }
  ]
});

const {
  modelVisible,
  operateType,
  editingData,
  handleEdit,
  handleAdd,
  checkedRowKeys,
  onBatchDeleted,
  onDeleted,
  fetchDataUrl
  // closeDrawer
} = useTableOperate(data, getData);

function handleUserStatus(row: User) {
  // 修改状态的二次确认
  const text =
    row.status?.toString() === CommonStatusEnum.ENABLE
      ? $t('page.manage.common.status.disable')
      : $t('page.manage.common.status.enable');
  const msg =
    $t('page.manage.user.confirmUpdateStatusPre') + text + row.username + $t('page.manage.user.confirmUpdateStatusSuf');

  // 修改数据
  row.status = row.status?.toString() === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE;

  window.$dialog?.info({
    title: $t('common.tip'),
    content: msg,
    positiveText: $t('common.confirm'),
    negativeText: $t('common.cancel'),
    onPositiveClick: () => {
      // 发起修改状态
      updateUserStatus(row.id);
    },
    onNegativeClick: () => {
      // 取消后，进行恢复按钮
      row.status =
        row.status?.toString() === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE;
    }
  });
}

async function handleBatchDelete() {
  // request
  const { error } = await deleteUsers(checkedRowKeys.value.join(','));

  await onBatchDeleted(error);
}

async function handleDelete(id: number) {
  window.$dialog?.warning({
    title: $t('common.tip'),
    content: $t('common.confirmDelete'),
    positiveText: $t('common.confirm'),
    negativeText: $t('common.cancel'),
    onPositiveClick: async () => {
      // request
      const { error } = await deleteUsers(id.toString());

      await onDeleted(error);
    }
  });
}

const newPassword = ref('');
/** 重置密码 */
async function handleResetPwd(row: User) {
  const msg = `${$t('common.input')}【${row.nickname}】${$t('page.manage.user.newPassword')}`;
  window.$dialog?.warning({
    title: $t('common.tip'),
    content: () =>
      h(
        NFormItem,
        {
          label: msg
        },
        {
          default: () => (
            <NInput
              value={newPassword.value}
              onInput={value => (newPassword.value = value)}
              type="password"
              show-password-on="click"
            />
          )
        }
      ),
    positiveText: $t('common.confirm'),
    negativeText: $t('common.cancel'),
    onPositiveClick: async () => {
      // request
      const { error } = await updateUserPassword(row.id, newPassword.value);
      if (!error) {
        window.$message?.success(`${$t('page.manage.user.passwordUpdateSuccess')}【${newPassword.value}】`);
        newPassword.value = '';
      }
    },
    onNegativeClick: () => {
      newPassword.value = '';
    }
  });
}

const assignUser = ref<User | null>(null);
function handleUserAssignRole(row: User) {
  assignUser.value = row;
  openUserAssignRoleModal();
}

function edit(id: number) {
  fetchDataUrl.value = getFetchUserUrl(id);
  handleEdit(id);
}

const deptTree = shallowRef<Api.Common.TreeOptions[]>([]);
const deptNameSearch = ref('');

async function getDeptTree() {
  const res = await fetchAllDeptOptions();

  if (!res.error) {
    if (!res.data[0] || !res.data[0].children) {
      deptTree.value = []; // 或者其他适当的默认值
    } else {
      deptTree.value = res.data[0].children;
    }
  }
}

const handleDeptTreeNodeClick: TreeOverrideNodeClickBehavior = ({ option }) => {
  searchParams.deptId = option.value as number;
  getData();
  return 'none';
};

onMounted(() => {
  getDeptTree();
});
</script>

<template>
  <NGrid x-gap="12" :cols="24" item-responsive responsive="screen">
    <NGridItem span="0 m:4 l:4">
      <div class="h-full overflow-hidden lt-sm:overflow-auto">
        <NCard>
          <NInput v-model:value="deptNameSearch" clearable :placeholder="$t('page.manage.dept.form.name')">
            <template #prefix>
              <icon-ep:search color="#d4d4d4" />
            </template>
          </NInput>
          <NTree
            :data="deptTree"
            :pattern="deptNameSearch"
            :show-irrelevant-nodes="false"
            key-field="value"
            :expand-on-click="false"
            virtual-scroll
            block-line
            :default-expand-all="true"
            class="m-t h-150"
            :override-default-node-click-behavior="handleDeptTreeNodeClick"
          />
        </NCard>
      </div>
    </NGridItem>
    <NGridItem span="24 m:20 l:20">
      <div class="h-full flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
        <UserSearch
          v-if="hasAuth('system:user:query')"
          v-model:model="searchParams"
          @reset="resetSearchParams"
          @search="getDataByPage"
        />
        <NCard
          :title="$t('page.manage.user.title')"
          :bordered="false"
          size="small"
          class="sm:flex-1-hidden card-wrapper"
        >
          <template #header-extra>
            <TableHeaderOperation
              v-model:columns="columnChecks"
              :disabled-delete="checkedRowKeys.length === 0"
              :loading="loading"
              create-auth="system:user:create"
              delete-auth="system:user:delete"
              @add="handleAdd"
              @delete="handleBatchDelete"
              @refresh="getData"
            />
          </template>
          <NDataTable
            v-model:checked-row-keys="checkedRowKeys"
            :columns="columns"
            :data="data"
            size="small"
            :flex-height="!appStore.isMobile"
            :scroll-x="962"
            :loading="loading"
            remote
            :row-key="row => row.id"
            :pagination="mobilePagination"
            class="sm:h-full"
          />
          <UserOperateModal
            v-model:visible="modelVisible"
            :operate-type="operateType"
            :row-data="editingData"
            @submitted="getDataByPage"
          />
        </NCard>

        <UserAssignRoleModal v-model:visible="userAssignRoleVisible" :row-data="assignUser" />
      </div>
    </NGridItem>
  </NGrid>
</template>

<style scoped></style>
